package com.xiaochen.product.service.impl;

import com.alibaba.fastjson.JSON;
import com.aliyuncs.utils.StringUtils;
import com.xiaochen.model.entity.product.Category;
import com.xiaochen.product.mapper.CategoryMapper;
import com.xiaochen.product.service.CategoryService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;

@Slf4j
@Service
public class CategoryServiceImpl implements CategoryService {

    @Autowired
    private CategoryMapper categoryMapper;

    @Autowired
    private RedisTemplate<String,String> redisTemplate;

    public static final String CATEGORY_ONE = "category:one";

    /**
     * 查询一级分类
     *
     * 定义redis缓存<K,V>里面的K = category:one
     *                      V = List<Category>数据库里面查询出来的一级分类的数据
     * @return
     */
    @Override
    public List<Category> selectOneCategory() {
        log.info("查询一级分类");
       // 1.从缓存中查询数据,判断是否存在一级分类
        //定义redis<K,V>的K,并为其设置值
        String categoryOneJson = redisTemplate.opsForValue().get(CATEGORY_ONE);
        // 2.如果存在,从缓存中获取数据并返回
        if (!StringUtils.isEmpty(categoryOneJson)){
            List<Category> existCategoryList = JSON.parseArray(categoryOneJson, Category.class);
            log.info("从缓存中查询一级分类数据");
            return existCategoryList;
        }
        // 3.如果不存在,就从数据库查询,
        List<Category> categoryList = categoryMapper.selectOneCategory();
        log.info("从数据库中查询一级分类数据");
        // 4.将数据保存到缓存中,并返回
        redisTemplate.opsForValue().set("category:one",JSON.toJSONString(categoryList),7, TimeUnit.DAYS);
        return categoryList;
    }

    /**
     * 查询商品分类树状结构(所有分类)
     * @return
     *
     *  跟上面的直接使用redisTemplate效果一样,都是为了将常用数据存储到缓存中,加快查询
     * 设置key为---category:all
     * category::all
     */
    @Cacheable(value = "category",key = "'all'")
    @Override
    public List<Category> findCategoryTree() {
        log.info("递归查询所有分类");
        // 查询商品分类,并封装为树状结构返回
        // 1.查询所有分类并返回
        List<Category> allCategoryList = categoryMapper.findAll();

        /*// 2.遍历所有分类的list集合,通过parent_id=0得到所有一级分类(通过递归查询所有的children,id=parent_id)
        // 2.1查询一级分类
        // 2.2查询一级分类下的所有二级分类
        // 2.3查询二级分类下的所有三级分类*/

        // **** 我在这个位置调用的递归方法实现的(因为知道只有三级可以直接用for循环或者stream流一层一层查询返回)
        return buildCategoryTree(0L,allCategoryList);
    }

    private List<Category> buildCategoryTree(Long parentId,List<Category> allCategoryList){
        List<Category> list = new ArrayList<>();
        for (Category category : allCategoryList){
            if (parentId.equals(category.getParentId().longValue())){
                list.add(category);
            }
        }
        for (Category category : list){
            category.setChildren(buildCategoryTree(category.getId(),allCategoryList));
        }
        return list;
    }
}
